home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Milan_1991 / Devcon91.4 / AppShell / Examples / Clipboard / ilbm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-01  |  20.8 KB  |  890 lines

  1. /*************************************************************************
  2.   *                                                                      *
  3.   *                            Preliminary                               *
  4.   *                        Amiga AppShell (tm)                           *
  5.   *                                                                      *
  6.   *  Copyright (c) 1990,1991 Commodore-Amiga, Inc. All Rights Reserved.  *
  7.   *                                                                      *
  8.   *   This software and information is proprietary, preliminary, and     *
  9.   *   subject to change without notice.                                  *
  10.   *                                                                      *
  11.   *                            DISCLAIMER                                *
  12.   *                                                                      *
  13.   *   THIS SOFTWARE IS PROVIDED "AS IS".                                 *
  14.   *   NO REPRESENTATIONS OR WARRANTIES ARE MADE WITH RESPECT TO THE      *
  15.   *   ACCURACY, RELIABILITY, PERFORMANCE, CURRENTNESS, OR OPERATION      *
  16.   *   OF THIS SOFTWARE, AND ALL USE IS AT YOUR OWN RISK.                 *
  17.   *   NEITHER COMMODORE NOR THE AUTHORS ASSUME ANY RESPONSIBILITY OR     *
  18.   *   LIABILITY WHATSOEVER WITH RESPECT TO YOUR USE OF THIS SOFTWARE.    *
  19.   *                                                                      *
  20.   *                          Non-Disclosure                              *
  21.   *                                                                      *
  22.   *   This information is not to be disclosed to any other company,      *
  23.   *   individual or party.  Discussion is to be restricted to CBM        *
  24.   *   approved discussion areas, such as the closed conferences on bix;  *
  25.   *   amiga.cert, amiga.com, amiga.beta/appshell.                        *
  26.   *                                                                      *
  27.   ************************************************************************
  28.   * Copyright (C) 1990 Commodore-Amiga, Inc.
  29.   * written by David N. Junod
  30.   */
  31.  
  32. /* ilbm.c --- read an IFF ILBM file into a record.
  33.  */
  34.  
  35. #include <exec/types.h>
  36. #include <exec/memory.h>
  37. #include <iff/ilbm.h>
  38. #include <intuition/intuition.h>
  39. #include <intuition/intuitionbase.h>
  40. #include <graphics/gfx.h>
  41. #include <graphics/displayinfo.h>
  42. #include <graphics/view.h>
  43. #include <libraries/dos.h>
  44. #include <libraries/dosextens.h>
  45. #include <libraries/iffparse.h>
  46. #include <libraries/prefs.h>
  47. #include <utility/tagitem.h>
  48. #include <workbench/workbench.h>
  49. #include <clib/macros.h>
  50. #include <clib/exec_protos.h>
  51. #include <clib/intuition_protos.h>
  52. #include <clib/graphics_protos.h>
  53. #include <clib/dos_protos.h>
  54. #include <clib/utility_protos.h>
  55. #include <clib/iffparse_protos.h>
  56. #include <clib/icon_protos.h>
  57. #include <pragmas/exec.h>
  58. #include <pragmas/dos.h>
  59. #include <pragmas/intuition.h>
  60. #include <pragmas/graphics.h>
  61. #include <pragmas/utility.h>
  62. #include <pragmas/iffparse.h>
  63. #include <pragmas/icon.h>
  64. #include <string.h>
  65.  
  66. #define VANILLA_COPY    0xC0
  67. #define NO_MASK        0xFF
  68.  
  69. extern struct Library *DOSBase, *SysBase, *IFFParseBase;
  70. extern struct Library *GfxBase, *IntuitionBase, *IconBase;
  71. extern struct DiskObject brush_icon;
  72.  
  73. /* ilbm.c */
  74. ILBM *ReadILBM (BPTR drawer, STRPTR name, struct TagItem * attrs);
  75. BOOL WriteILBM (BPTR drawer, STRPTR name, ILBM *ir, BOOL);
  76. VOID FreeILBM (ILBM * ilbm);
  77. ILBM *GetILBM (struct IFFHandle * iff);
  78. BOOL GetBMHD (struct IFFHandle * iff, struct BitMapHeader * bmhd);
  79. BOOL PutBMHD (struct IFFHandle * iff, struct BitMapHeader * bmhd, ILBM *ir);
  80. BOOL PutILBM (struct IFFHandle * iff, ILBM * ilbm);
  81. WORD GetColors (struct IFFHandle * iff, struct ColorRegister * cmap);
  82. BOOL PutColors (struct IFFHandle * iff, struct BitMapHeader * bmhd, struct ColorRegister * cmap);
  83. void GetHotSpot (struct IFFHandle * iff, struct Point2D * grab, WORD, WORD);
  84. BOOL PutHotSpot (struct IFFHandle * iff, struct Point2D * grab);
  85. BOOL GetBody (struct IFFHandle * iff, struct BitMapHeader * bmhd, struct BitMap * bm);
  86. LONG loadbody(struct IFFHandle * iff, struct BitMap *bitmap, struct BitMapHeader *bmhd);
  87. BOOL GetLine (struct IFFHandle * iff, UBYTE * buf, WORD wide, WORD deep, UBYTE cmptype);
  88. BOOL PutBody (struct IFFHandle * iff, struct BitMapHeader * bmhd, struct BitMap * bitmap);
  89. BOOL AllocBMRast (struct BitMap * bm, BYTE depth, WORD width, WORD height);
  90.  
  91. #define    BPR(w)        ((w) + 15 >> 4 << 1)    /* Bytes per row */
  92.  
  93. /* Properties that we can deal with */
  94. LONG ilbmprops[] =
  95. {
  96.     ID_ILBM, ID_BMHD,
  97.     ID_ILBM, ID_CMAP,
  98.     ID_ILBM, ID_GRAB,
  99.     ID_ILBM, ID_CAMG
  100. };
  101.  
  102. ILBM *ReadILBM (BPTR drawer, STRPTR name, struct TagItem * attrs)
  103. {
  104.     struct Process *proc = (struct Process *) FindTask (NULL);
  105.     struct IFFHandle *iff;
  106.     ILBM *ilbm = NULL;
  107.     BPTR lock = NULL;
  108.  
  109.     /* Clear the error field */
  110.     proc->pr_Result2 = NULL;
  111.  
  112.     /* Did they give a directory lock? */
  113.     if (drawer)
  114.     {
  115.     /* Go to the required directory */
  116.     lock = CurrentDir (drawer);
  117.     }
  118.  
  119.     /* Allocate an IFF handle */
  120.     if (iff = AllocIFF ())
  121.     {
  122.     /* Open the preference file */
  123.     if (iff->iff_Stream = Open (name, MODE_OLDFILE))
  124.     {
  125.         /* Indicate that the IFF handle is for a file */
  126.         InitIFFasDOS (iff);
  127.  
  128.         if (ilbm = GetILBM (iff))
  129.         {
  130.         }
  131.  
  132.         /* Close the file */
  133.         Close (iff->iff_Stream);
  134.     }
  135.     else
  136.     {
  137.         /* Couldn't open file, Result2 already set by Open */
  138.     }
  139.  
  140.     /* Free the IFF handle */
  141.     FreeIFF (iff);
  142.     }
  143.     else
  144.     {
  145.     /* Not enough memory */
  146.     proc->pr_Result2 = ERROR_NO_FREE_STORE;
  147.     }
  148.  
  149.     if (lock)
  150.     {
  151.     CurrentDir (lock);
  152.     }
  153.  
  154.     return (ilbm);
  155. }
  156.  
  157. BOOL WriteILBM (BPTR drawer, STRPTR name, ILBM *ir, BOOL icon)
  158. {
  159.     struct Process *proc = (struct Process *) FindTask (NULL);
  160.     struct IFFHandle *iff;
  161.     BOOL retval = FALSE;
  162.     BPTR lock = NULL;
  163.  
  164.     /* Clear the error field */
  165.     proc->pr_Result2 = NULL;
  166.  
  167.     /* Did they give a directory lock? */
  168.     if (drawer)
  169.     {
  170.     /* Go to the required directory */
  171.     lock = CurrentDir (drawer);
  172.     }
  173.  
  174.     /* Allocate an IFF handle */
  175.     if (iff = AllocIFF ())
  176.     {
  177.     /* Open the preference file */
  178.     if (iff->iff_Stream = Open (name, MODE_NEWFILE))
  179.     {
  180.         /* Indicate that the IFF handle is for a file */
  181.         InitIFFasDOS (iff);
  182.  
  183.         /* Open the IFF handle for writing */
  184.         if (OpenIFF (iff, IFFF_WRITE) == 0L)
  185.         {
  186.         /* Place it in the clipboard */
  187.         if (PutILBM (iff, ir))
  188.         {
  189.             /* wrote ilbm to file */
  190.             retval = TRUE;
  191.         }
  192.         else
  193.         {
  194.             /* Couldn't write ilbm */
  195.         }
  196.  
  197.         /* Close the IFF handle */
  198.         CloseIFF (iff);
  199.         }
  200.         else
  201.         {
  202.         /* Couldn't open IFF for writing */
  203.         }
  204.  
  205.         /* Close the file */
  206.         Close (iff->iff_Stream);
  207.  
  208.         /* Able to write ILBM? */
  209.         if (retval)
  210.         {
  211.         /* Clear the execute file attribute */
  212.         SetProtection (name, FIBF_EXECUTE);
  213.  
  214.         /* Do they want icons? */
  215.         if (icon && IconBase)
  216.         {
  217.             /* Write an icon for the brush */
  218.             PutDiskObject (name, &brush_icon);
  219.         }
  220.         }
  221.         else
  222.         {
  223.         /* Delete the partial file */
  224.         DeleteFile (name);
  225.         }
  226.     }
  227.     else
  228.     {
  229.         /* Couldn't open file, Result2 already set by Open */
  230.     }
  231.  
  232.     /* Free the IFF handle */
  233.     FreeIFF (iff);
  234.     }
  235.     else
  236.     {
  237.     /* Not enough memory */
  238.     proc->pr_Result2 = ERROR_NO_FREE_STORE;
  239.     }
  240.  
  241.     if (lock)
  242.     {
  243.     CurrentDir (lock);
  244.     }
  245.  
  246.     return (retval);
  247. }
  248.  
  249. ILBM *GetILBM (struct IFFHandle * iff)
  250. {
  251.     ILBM *ilbm = NULL;
  252.     LONG msize = sizeof (ILBM);
  253.  
  254.     /* Open the IFF handle for reading */
  255.     if (!(OpenIFF (iff, IFFF_READ)))
  256.     {
  257.     /* Register collection chunks */
  258.     PropChunks (iff, ilbmprops, 4);
  259.  
  260.     /* Register where we want to stop */
  261.     StopChunk (iff, ID_ILBM, ID_BODY);
  262.  
  263.     /* Parse the file, stopping at the body */
  264.     if (ParseIFF (iff, IFFPARSE_SCAN) == 0L)
  265.     {
  266.         /* Allocate an ILBM record */
  267.         if (ilbm = (ILBM *) AllocVec (msize, MEMF_CLEAR))
  268.         {
  269.         struct BitMapHeader bmhd;
  270.  
  271.         /* See if we collected a bitmap header */
  272.         if (GetBMHD (iff, &bmhd))
  273.         {
  274.             struct BitMap *bm = &(ilbm->ir_BMap);
  275.  
  276.             /* Get the size information */
  277.             ilbm->ir_Width = bmhd.w;
  278.             ilbm->ir_Height = bmhd.h;
  279.             ilbm->ir_Depth = bmhd.nplanes;
  280.  
  281.             /* Allocate a bitmap w/rasters to hold the image */
  282.             if (AllocBMRast (bm, ilbm->ir_Depth, ilbm->ir_Width, ilbm->ir_Height))
  283.             {
  284.             struct ColorRegister pp_Colors[MAXCOLORS];
  285.             struct StoredProperty *sp;
  286.             ULONG mode = NULL;
  287.  
  288.             /* Initialize the rastport */
  289.             InitRastPort (&(ilbm->ir_RPort));
  290.             ilbm->ir_RPort.BitMap = bm;
  291.             SetRast (&(ilbm->ir_RPort), 0);
  292.  
  293.             /* See if we have a CAMG chunk */
  294.             if (sp = FindProp (iff, ID_ILBM, ID_CAMG))
  295.             {
  296.                 /* Get the mode ID */
  297.                 mode  = *((ULONG *) sp->sp_Data);
  298.             }
  299.  
  300.             /* See if we have a valid ModeID */
  301.             if (((mode & (0xffff0000)) && (!(mode & 0x00001000))) ||
  302.                 (mode == NULL))
  303.             {
  304.                 /* We have to fabricate a correct ModeID */
  305.                 mode = LORES_KEY;
  306.                 if (ilbm->ir_Width >= 640)
  307.                 mode = HIRES;
  308.                 if (ilbm->ir_Height >= 400)
  309.                 mode |= LACE;
  310.                 if (ilbm->ir_Depth == 6)
  311.                 mode |= HAM;
  312.             }
  313.  
  314.             /* Remember the ModeID */
  315.             ilbm->ir_ModeID = mode;
  316.  
  317.             /* Get the color map */
  318.             if (ilbm->ir_NumColors = GetColors (iff, &(pp_Colors[0])))
  319.             {
  320.                 WORD i, r, g, b;
  321.  
  322.                 for (i = 0; i < ilbm->ir_NumColors; i++)
  323.                 {
  324.                 r = (pp_Colors[i].red >> 4);
  325.                 g = (pp_Colors[i].green >> 4);
  326.                 b = (pp_Colors[i].blue >> 4);
  327.  
  328.                 ilbm->ir_CRegs[i] = (r << 8) | (g << 4) | (b);
  329.                 }
  330.             }
  331.             else
  332.             {
  333.                 /* Couldn't get colors */
  334.             }
  335.  
  336.             /* Get the hot spot */
  337.             GetHotSpot (iff, &(ilbm->ir_Grab), ilbm->ir_Width, ilbm->ir_Height);
  338.  
  339.             /* Get the image data itself */
  340.             if (GetBody (iff, &bmhd, bm))
  341.             {
  342.                 /* Close the IFF handle!!! */
  343.                 CloseIFF (iff);
  344.  
  345.                 return (ilbm);
  346.  
  347.             }    /* End of get body */
  348.             else
  349.             {
  350.                 /* couldn't get body */
  351.             }
  352.             }        /* End of allocate BM */
  353.             else
  354.             {
  355.             /* couldn't allocate bitmap */
  356.             }
  357.         }        /* End of get bitmap header */
  358.         else
  359.         {
  360.             /* no bitmap header */
  361.         }
  362.  
  363.         /* Free the ilbm buffer */
  364.         FreeILBM (ilbm);
  365.         }
  366.         else
  367.         {
  368.         /* not enough memory */
  369.         }
  370.     }
  371.     else
  372.     {
  373.         /* scan error */
  374.     }
  375.  
  376.     /* Close the IFF handle */
  377.     CloseIFF (iff);
  378.     }
  379.     else
  380.     {
  381.     /* couldn't open stream */
  382.     }
  383.  
  384.     return (NULL);
  385. }
  386.  
  387. BOOL PutILBM (struct IFFHandle * iff, ILBM * ilbm)
  388. {
  389.     BOOL status = FALSE;
  390.     LONG retval;
  391.  
  392.     if (iff && ilbm)
  393.     {
  394.     /* Open the IFF handle for reading */
  395.     if (!(OpenIFF (iff, IFFF_WRITE)))
  396.     {
  397.         /* Start writing the text ... */
  398.         if ((retval = PushChunk (iff, ID_ILBM, ID_FORM, -1L)) == 0)
  399.         {
  400.         struct BitMapHeader *bmhd;
  401.         LONG msize = sizeof (struct BitMapHeader);
  402.  
  403.         if (bmhd = AllocMem (msize, MEMF_CLEAR))
  404.         {
  405.             if (PutBMHD (iff, bmhd, ilbm))
  406.             {
  407.             /* Do they have a color table to output */
  408.             if (ilbm->ir_NumColors > 0L)
  409.             {
  410.                 struct ColorRegister pp_Colors[MAXCOLORS];
  411.                 WORD i, r, g, b;
  412.  
  413.                 for (i = 0; i < (ilbm->ir_NumColors); i++)
  414.                 {
  415.                 r = (ilbm->ir_CRegs[i] & 0xF00) >> 4;
  416.                 g = (ilbm->ir_CRegs[i] & 0xF0);
  417.                 b = (ilbm->ir_CRegs[i] << 4);
  418.  
  419.                 pp_Colors[i].red = r;
  420.                 pp_Colors[i].green = g;
  421.                 pp_Colors[i].blue = b;
  422.                 }
  423.  
  424.                 /* Write the colors */
  425.                 PutColors (iff, bmhd, pp_Colors);
  426.             }
  427.  
  428.             if (PutBody (iff, bmhd, &(ilbm->ir_BMap)))
  429.             {
  430.                 status = TRUE;
  431.             }
  432.             }
  433.  
  434.             FreeMem (bmhd, msize);
  435.         }
  436.         else
  437.         {
  438.             /* couldn't allocate room for bitmap header */
  439.         }
  440.  
  441.         /* Finish out the entire write */
  442.         PopChunk (iff);
  443.         }
  444.         else
  445.         {
  446.         /* Couldn't start clip */
  447.         }
  448.  
  449.         /* Close the IFF handle */
  450.         CloseIFF (iff);
  451.     }
  452.     else
  453.     {
  454.         /* couldn't open for writing */
  455.     }
  456.     }
  457.  
  458.     return (status);
  459. }
  460.  
  461. BOOL GetBMHD (struct IFFHandle *iff, struct BitMapHeader *bmhd)
  462. {
  463.     struct StoredProperty *sp;
  464.  
  465.     if (sp = FindProp (iff, ID_ILBM, ID_BMHD))
  466.     {
  467.     *bmhd = *((struct BitMapHeader *) sp->sp_Data);
  468.     return (TRUE);
  469.     }
  470.  
  471.     return (FALSE);
  472. }
  473.  
  474. BOOL PutBMHD (struct IFFHandle *iff, struct BitMapHeader *bmhd, ILBM *ir)
  475. {
  476.     struct BitMap *bm = &(ir->ir_BMap);
  477.  
  478.     bmhd->w = bm->BytesPerRow * 8;
  479.     bmhd->h = bm->Rows;
  480.     bmhd->x = 0;
  481.     bmhd->y = 0;
  482.     bmhd->nplanes = bm->Depth;
  483.     bmhd->Masking = mskHasTransparentColor;
  484.     bmhd->Compression = cmpNone;
  485.  
  486. /*     bmhd->Compression = cmpByteRun1; */
  487.  
  488.     bmhd->pad1 = 0;
  489.     bmhd->TransparentColor = 0;
  490.     bmhd->XAspect = 10;
  491.     bmhd->YAspect = 11;
  492.     bmhd->PageWidth = ir->ir_Width;
  493.     bmhd->PageHeight = ir->ir_Height;
  494.  
  495.     if ((PushChunk (iff, 0, ID_BMHD, sizeof (struct BitMapHeader))) == 0L)
  496.     {
  497.     if ((WriteChunkBytes (iff, bmhd, sizeof (struct BitMapHeader))) ==
  498.         sizeof (struct BitMapHeader))
  499.     {
  500.         if ((PopChunk (iff)) == 0L)
  501.         {
  502.         return (TRUE);
  503.         }
  504.     }
  505.     }
  506.  
  507.     return (FALSE);
  508. }
  509.  
  510. WORD
  511. GetColors (struct IFFHandle * iff, struct ColorRegister * cmap)
  512. {
  513.     struct ColorRegister *rgb;
  514.     struct StoredProperty *sp;
  515.     WORD i, ncolors = 0;
  516.  
  517.     if (sp = FindProp (iff, ID_ILBM, ID_CMAP))
  518.     {
  519.     /* Compute the actual number of colors we need to convert. */
  520.     i = ncolors = MIN (MAXCOLORS, (sp->sp_Size / 3L));
  521.  
  522.     rgb = (struct ColorRegister *) sp->sp_Data;
  523.     while (i--)
  524.     {
  525.         *cmap = *rgb;
  526.         cmap++;
  527.         rgb++;
  528.     }
  529.     }
  530.  
  531.     return (ncolors);
  532. }
  533.  
  534. BOOL
  535. PutColors (struct IFFHandle *iff, struct BitMapHeader *bmhd, struct ColorRegister *cmap)
  536. {
  537.  
  538.     if (cmap == NULL)
  539.     return (FALSE);
  540.  
  541.     if ((PushChunk (iff, 0, ID_CMAP, IFFSIZE_UNKNOWN)) == 0L)
  542.     {
  543.     if ((WriteChunkRecords (iff, cmap, sizeof (struct ColorRegister),
  544.                 (1 << bmhd->nplanes))) == (1 << bmhd->nplanes))
  545.     {
  546.         if ((PopChunk (iff)) == 0L)
  547.         {
  548.         return (TRUE);
  549.         }
  550.     }
  551.     }
  552.  
  553.     return (FALSE);
  554. }
  555.  
  556. VOID
  557. GetHotSpot (struct IFFHandle *iff, struct Point2D *grab, WORD width, WORD height)
  558. {
  559.     struct StoredProperty *sp;
  560.  
  561.     if (sp = FindProp (iff, ID_ILBM, ID_GRAB))
  562.     {
  563.     *grab = *((struct Point2D *) sp->sp_Data);
  564.     }
  565.     else
  566.     {
  567.     grab->x = 0;
  568.     grab->y = 0;
  569.     }
  570.  
  571.     if ((grab->x >= width) || (grab->y >= height))
  572.     {
  573.     grab->x = 0;
  574.     grab->y = 0;
  575.     }
  576. }
  577.  
  578. BOOL PutHotSpot (struct IFFHandle *iff, struct Point2D *grab)
  579. {
  580.     if (grab)
  581.     {
  582.     if ((PushChunk (iff, 0, ID_GRAB, sizeof (struct Point2D))) == 0L)
  583.     {
  584.         if ((WriteChunkBytes (iff, grab, sizeof (struct Point2D))) ==
  585.         sizeof (struct Point2D))
  586.         {
  587.         if ((PopChunk (iff)) == 0L)
  588.         {
  589.             return (TRUE);
  590.         }
  591.         }
  592.     }
  593.     }
  594.  
  595.     return (FALSE);
  596. }
  597.  
  598. BOOL
  599. GetBody (struct IFFHandle *iff, struct BitMapHeader *bmhd, struct BitMap *bm)
  600. {
  601.     BOOL status = FALSE;
  602.     WORD i, n, p;
  603.     UWORD *srcline, *destline;
  604.     struct BitMap mapcopy, *destmap;
  605.     UBYTE *linebuf, *csrcline;
  606.     WORD srcw, destw;        /* src and dest width in BYTES */
  607.     WORD srch, desth;        /* src and dest height (rows) */
  608.     WORD srcd, destd;        /* src and dest depth */
  609.     WORD deep, rows, mod;
  610.     LONG msize;
  611.  
  612.     /* Check compression type. */
  613.     if ((bmhd->Compression != cmpNone) && (bmhd->Compression != cmpByteRun1))
  614.     {
  615.     return (status);
  616.     }
  617.  
  618.     /* Copy the bitmap pointer */
  619.     destmap = bm;
  620.  
  621.     /* Copy the bitmap */
  622.     mapcopy = *destmap;
  623.  
  624.     /* Set up our size variables */
  625.     srcw = BPR (bmhd->w);
  626.     srch = bmhd->h;
  627.     srcd = bmhd->nplanes;
  628.     destw = mapcopy.BytesPerRow;
  629.     desth = mapcopy.Rows;
  630.     destd = mapcopy.Depth;
  631.     rows = MIN (srch, desth);
  632.  
  633.     mod = destw - srcw;
  634.     if (mod < 0)
  635.     mod = -mod;
  636.  
  637.     if (bmhd->Masking == mskHasMask)
  638.     srcd++;
  639.  
  640.     deep = MIN (srcd, destd);
  641.  
  642.     /*
  643.      * Allocate a one-line buffer to load imagery in.  The line is then copied
  644.      * into the destination bitmap.  This seeming duplicity makes clipping
  645.      * loaded images easier.
  646.      */
  647.  
  648.     msize = (LONG) (srcw * srcd);
  649.     if (linebuf = (UBYTE *) AllocVec (msize, MEMF_CLEAR))
  650.     {
  651.  
  652.     /*
  653.      * Load the BODY into the allocated line buffer, then copy into the
  654.      * destination bitmap.
  655.      */
  656.     for (i = rows; i--;)
  657.     {
  658.         if (!(status = GetLine (iff, linebuf, srcw, srcd, bmhd->Compression)))
  659.         break;
  660.  
  661.         srcline = (UWORD *) linebuf;
  662.         for (p = 0; p < deep; p++)
  663.         {
  664.         destline = (UWORD *) mapcopy.Planes[p];
  665.         *destline = 0xffff;
  666.         n = (MIN (srcw, destw)) >> 1;    /* convert #bytes to #words */
  667.  
  668.         while (n--)
  669.             *destline++ = *srcline++;
  670.  
  671.         if (srcw > destw)
  672.         {
  673.             csrcline = (UBYTE *) srcline;
  674.             csrcline += mod;
  675.             srcline = (UWORD *) csrcline;
  676.         }
  677.         mapcopy.Planes[p] += destw;
  678.         }
  679.     }
  680.  
  681.     /* Free the temporary line buffer */
  682.     FreeVec ((APTR) linebuf);
  683.  
  684.     /* Say that it worked */
  685.     status = TRUE;
  686.     }
  687.  
  688.     return (status);
  689. }
  690.  
  691. BOOL GetLine (iff, buf, wide, deep, cmptype)
  692.     struct IFFHandle *iff;
  693.     UBYTE *buf;
  694.     WORD wide, deep;
  695.     UBYTE cmptype;
  696. {
  697.  
  698.     if (cmptype == cmpNone)
  699.     {                /* No compression */
  700.     LONG big = wide * deep;
  701.  
  702.     if (ReadChunkBytes (iff, buf, big) != big)
  703.         return (FALSE);
  704.     }
  705.     else
  706.     {
  707.     WORD i, so_far;
  708.     UBYTE *dest = buf;
  709.     BYTE len;
  710.  
  711.     for (i = deep; i--;)
  712.     {
  713.         so_far = wide;
  714.         while (so_far > 0)
  715.         {
  716.         if (ReadChunkBytes (iff, &len, 1L) != 1)
  717.             return (FALSE);
  718.  
  719.         if (len >= 0)
  720.         {        /* Literal byte copy  */
  721.             if ((so_far -= ++len) < 0)
  722.             break;
  723.             if (ReadChunkBytes (iff, dest, (LONG) len) != len)
  724.             return (FALSE);
  725.             dest += len;
  726.         }
  727.         else if ((UBYTE) len == 128)
  728.              /* NOP  */ ;
  729.  
  730.         else if (len < 0)
  731.         {        /* Replication count  */
  732.             UBYTE byte;
  733.  
  734.             len = -len + 1;
  735.             if ((so_far -= len) < 0)
  736.             break;
  737.             if (ReadChunkBytes (iff, &byte, 1L) != 1)
  738.             return (FALSE);
  739.             while (--len >= 0)
  740.             *dest++ = byte;
  741.         }
  742.         }
  743.         if (so_far)
  744.         {
  745.         return (FALSE);
  746.         }
  747.     }
  748.     buf += wide;
  749.     }
  750.     return (TRUE);
  751. }
  752.  
  753. BOOL PutBody (iff, bmhd, bitmap)
  754.     struct IFFHandle *iff;
  755.     struct BitMapHeader *bmhd;
  756.     struct BitMap *bitmap;
  757. {
  758.     UWORD i;
  759.     UBYTE p, *pptr;
  760.  
  761.     if ((PushChunk (iff, 0, ID_BODY, IFFSIZE_UNKNOWN)) == 0L)
  762.     {
  763.     for (i = 0; i < bmhd->h; i++)
  764.     {
  765.         for (p = 0; p < bmhd->nplanes; p++)
  766.         {
  767.         pptr = (UBYTE *) bitmap->Planes[p];
  768.  
  769.         WriteChunkBytes (iff, &pptr[i * bitmap->BytesPerRow],
  770.                  2 * ((bmhd->w + 15) / 16));
  771.         }
  772.     }
  773.  
  774.     if ((PopChunk (iff)) == 0L)
  775.     {
  776.         return (TRUE);
  777.     }
  778.     }
  779.  
  780.     return (FALSE);
  781. }
  782.  
  783. BOOL AllocBMRast (struct BitMap *bm, BYTE depth, WORD width, WORD height)
  784. {
  785.     WORD i;
  786.  
  787.     /* Initialize the BitMap */
  788.     InitBitMap (bm, depth, width, height);
  789.  
  790.     /* Allocate the rasters */
  791.     for (i = 0; i < depth; i++)
  792.     {
  793.     if (!(bm->Planes[i] = (PLANEPTR) AllocRaster (width, height)))
  794.     {
  795.         return (FALSE);
  796.     }
  797.     }
  798.  
  799.     return (TRUE);
  800. }
  801.  
  802. VOID FreeILBM (ILBM * ilbm)
  803. {
  804.  
  805.     if (ilbm)
  806.     {
  807.     struct BitMap *bm = &(ilbm->ir_BMap);
  808.     WORD i;
  809.  
  810.     /* Free each plane of the bitmap */
  811.     for (i = 0; i < ilbm->ir_Depth; i++)
  812.     {
  813.         if (bm->Planes[i])
  814.         {
  815.         /* Free the raster */
  816.         FreeRaster (bm->Planes[i], ilbm->ir_Width, ilbm->ir_Height);
  817.         bm->Planes[i] = NULL;
  818.         }
  819.     }
  820.  
  821.     /* Free the ILBM record */
  822.     FreeVec ((APTR) ilbm);
  823.     }
  824. }
  825.  
  826. UWORD chip brushI1Data[] =
  827. {
  828. /* Plane 0 */
  829.     0x0000,0x0000,0x0000,0x0400,0x0000,0x0000,0x0000,0x0C00,
  830.     0x0000,0x0000,0x0000,0x0C00,0x0067,0xE7F0,0x0000,0x0C00,
  831.     0x0066,0x0600,0x0000,0x0C00,0x0067,0xC7C0,0x0060,0x0C00,
  832.     0x0066,0x0600,0x0180,0x0C00,0x0066,0x0600,0x0600,0x0C00,
  833.     0x0066,0x0600,0x1800,0x0C00,0x0000,0x0000,0x6000,0x0C00,
  834.     0x0000,0x0003,0x8000,0x0C00,0x0000,0x000E,0x0000,0x0C00,
  835.     0x0000,0x0038,0x0000,0x0C00,0x0000,0x00E0,0x0000,0x0C00,
  836.     0x0000,0x0380,0x0000,0x0C00,0x0000,0x0E00,0x0000,0x0C00,
  837.     0x0000,0x7800,0xAA00,0x0C00,0x0003,0xE0AA,0x8000,0x0C00,
  838.     0x00FE,0xAAA0,0x0000,0x0C00,0x0000,0x0000,0x0000,0x0C00,
  839.     0x0000,0x0000,0x0000,0x0C00,0x7FFF,0xFFFF,0xFFFF,0xFC00,
  840. /* Plane 1 */
  841.     0xFFFF,0xFFFF,0xFFFF,0xF800,0xD555,0x5555,0x5555,0x5000,
  842.     0xD555,0x5555,0x5555,0x5000,0xD510,0x1005,0x5555,0x5000,
  843.     0xD511,0x5155,0x5555,0x5000,0xD510,0x1015,0x5515,0x5000,
  844.     0xD511,0x5155,0x5455,0x5000,0xD511,0x5155,0x5155,0x5000,
  845.     0xD511,0x5155,0x4555,0x5000,0xD555,0x5555,0x1555,0x5000,
  846.     0xD555,0x5554,0x5555,0x5000,0xD555,0x5551,0x5555,0x5000,
  847.     0xD555,0x5545,0x5555,0x5000,0xD555,0x5515,0x5555,0x5000,
  848.     0xD555,0x5455,0x5555,0x5000,0xD555,0x5155,0x5555,0x5000,
  849.     0xD555,0x7D55,0xFF55,0x5000,0xD557,0xF5FF,0xD555,0x5000,
  850.     0xD5FF,0xFFF5,0x5555,0x5000,0xD555,0x5555,0x5555,0x5000,
  851.     0xD555,0x5555,0x5555,0x5000,0x8000,0x0000,0x0000,0x0000,
  852. };
  853.  
  854. struct Image brushI1 =
  855. {
  856.     0, 0,            /* Upper left corner */
  857.     54, 22, 2,            /* Width, Height, Depth */
  858.     brushI1Data,        /* Image data */
  859.     0x0003, 0x0000,        /* PlanePick, PlaneOnOff */
  860.     NULL            /* Next image */
  861. };
  862.  
  863. struct DiskObject brush_icon =
  864. {
  865.     WB_DISKMAGIC,        /* Magic Number */
  866.     WB_DISKVERSION,        /* Version */
  867.     {                /* Embedded Gadget Structure */
  868.     NULL,            /* Next Gadget Pointer */
  869.     0, 0, 54, 23,        /* Left,Top,Width,Height */
  870.     GADGIMAGE | GADGHCOMP,    /* Flags */
  871.     RELVERIFY,        /* Activation Flags */
  872.     BOOLGADGET,        /* Gadget Type */
  873.     (APTR)&brushI1,        /* Render Image */
  874.     NULL,            /* Select Image */
  875.     NULL,            /* Gadget Text */
  876.     NULL,            /* Mutual Exclude */
  877.     NULL,            /* Special Info */
  878.     0,            /* Gadget ID */
  879.     NULL,            /* User Data */
  880.     },
  881.     WBPROJECT,            /* Icon Type */
  882.     (char *)"SYS:Utilities/Display",/* Default Tool */
  883.     NULL,            /* Tool Type Array */
  884.     NO_ICON_POSITION,        /* Current X */
  885.     NO_ICON_POSITION,        /* Current Y */
  886.     NULL,            /* Drawer Structure */
  887.     NULL,            /* Tool Window */
  888.     0                /* Stack Size */
  889. };
  890.